<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Reconciliation as ReconciliationModel;
use think\Db;
use think\Request;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;

/**
 * 对账管理接口
 */
class Reconciliation extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = ['*'];

    /**
     * 获取对账列表
     */
    public function getReconciliationList()
    {
        $params = $this->request->post();
        $page = $this->request->post('page', 1);
        $pageSize = $this->request->post('pageSize', 20);
        $action = $this->request->post('action', 'list'); // 新增：action参数，list或export
        
 
        
        if ($action === 'delete') {
            return $this->handleDelete($params);
        }

        // 构建查询条件
        $where = $this->buildWhere($params);

        // 普通列表查询
        $total = Db::name('reconciliation r')
            ->join('fa_user s', 'r.staff_id = s.id', 'left')
            ->join('fa_user u', 'r.user_id = u.id', 'left')
            ->field('r.*, s.name as staff_name, u.name as user_name')
            ->where($where)
            ->count();

        $list = Db::name('reconciliation r')
            ->join('fa_user s', 'r.staff_id = s.id', 'left')
            ->join('fa_user u', 'r.user_id = u.id', 'left')
            ->field('r.*, s.name as staff_name, u.name as user_name')
            ->where($where)
            ->order('r.id', 'desc')
            ->page($page, $pageSize)
            ->select();


        $ids = Db::name('reconciliation r')
            ->join('fa_user s', 'r.staff_id = s.id', 'left')
            ->join('fa_user u', 'r.user_id = u.id', 'left')
            ->field('r.*, s.name as staff_name, u.name as user_name')
            ->where($where)
            ->order('r.id', 'desc')
            ->column('r.id');
            
        $ids=implode(',',$ids);

        // 处理数据
        $request = \think\Request::instance();
        $domain = $request->domain();
        foreach ($list as $k => $v) {
   
            // 处理发票图片字段，添加完整域名
            if (!empty($v['invoice']) && is_string($v['invoice'])) {
                $invoice = json_decode($v['invoice'], true);
                if (is_array($invoice)) {
                    foreach ($invoice as $key => $value) {
                        $invoice[$key] = $domain . $value;
                    }
                    $list[$k]['invoice'] = $invoice;
                }
            }
                // 处理发票文件字段，添加完整域名
            if (!empty($v['file']) && is_string($v['file'])) {
                $file = json_decode($v['file'], true);
                if (is_array($file)) {
                    foreach ($file as $key => $value) {
                        $file[$key]['url'] = $domain . $value['url'];
                    }
                    $list[$k]['file'] = $file;
                }
            }

        }

        $this->success('请求成功', ['list' => $list, 'total' => $total, 'idlist'=>$ids]);
    }

    /**
     * 创建对账记录
     */
    public function createReconciliation()
    {
        $data = $this->request->post();
        
        // 参数验证
        if (empty($data['productName'])) {
            $this->error('产品名称不能为空');
        }
        if (empty($data['name'])) {
            $this->error('对接人不能为空');
        }
        if (empty($data['amount'])) {
            $this->error('金额不能为空');
        }

        // 处理发票字段
        if (!empty($data['invoice']) && is_array($data['invoice'])) {
            $invoice = $data['invoice'];
            foreach ($invoice as $key => $value) {
                $invoice[$key] = removeDomainFromImageUrl($value);
            }
            $data['invoice'] = json_encode($invoice, JSON_UNESCAPED_UNICODE);
        }
      
        // 处理pdf字段
        if (!empty($data['file']) && is_array($data['file'])) {
            $file = $data['file'];

            
            foreach ($file as $key => $value) {
                $file[$key]['url'] = removeDomainFromImageUrl($value['url']);
            }
            $data['file'] = json_encode($file, JSON_UNESCAPED_UNICODE);
       }


        // 处理日期字段
        if (!empty($data['reconciletime'])) {
            $data['reconciletime'] = date('Y-m-d H:i:s', strtotime($data['reconciletime']));
        }

        // 设置用户信息
        $data['staff_id'] = $this->auth->id;
        $data['user_id'] = $this->auth->id;
      

        $reconciliation = new ReconciliationModel();
        $result = $reconciliation->save($data);

        if ($result !== false) {
            $this->success('创建成功');
        } else {
            $this->error('创建失败');
        }
    }

    /**
     * 更新对账记录
     */
    public function updateReconciliation()
    {
        $data = $this->request->post();

        if (empty($data['id'])) {
            $this->error('缺少ID');
        }

        // 参数验证
        if (empty($data['productName'])) {
            $this->error('产品名称不能为空');
        }
        if (empty($data['name'])) {
            $this->error('对接人不能为空');
        }
        if (empty($data['amount'])) {
            $this->error('金额不能为空');
        }

        
        // 处理发票字段
        if (!empty($data['invoice']) && is_array($data['invoice'])) {
            $invoice = $data['invoice'];
            foreach ($invoice as $key => $value) {
                $invoice[$key] = removeDomainFromImageUrl($value);
            }
            $data['invoice'] = json_encode($invoice, JSON_UNESCAPED_UNICODE);
        }

            // 处理pdf字段
        if (!empty($data['file']) && is_array($data['file'])) {
                $file = $data['file'];

              
                foreach ($file as $key => $value) {
                    $file[$key]['url'] = removeDomainFromImageUrl($value['url']);
                }
                $data['file'] = json_encode($file, JSON_UNESCAPED_UNICODE);
       }
        // 处理日期字段
        if (!empty($data['reconciletime'])) {
            $data['reconciletime'] = date('Y-m-d H:i:s', strtotime($data['reconciletime']));
        }
        unset($data['staff_name']);
        unset($data['user_name']);
        unset($data['user_id']);
        unset($data['createtime']);


        $data['updatetime'] = date('Y-m-d H:i:s');

        $reconciliation = new ReconciliationModel();
        $result = $reconciliation->where('id', $data['id'])->update($data);

        if ($result !== false) {
            $this->success('更新成功');
        } else {
            $this->error('更新失败');
        }
    }

    /**
     * 删除对账记录
     */
    public function deleteReconciliation()
    {
        $id = $this->request->post('id');
        if (empty($id)) {
            $this->error('缺少ID');
        }

        $reconciliation = new ReconciliationModel();
        $result = $reconciliation->where('id', $id)->delete();

        if ($result !== false) {
            $this->success('删除成功');
        } else {
            $this->error('删除失败');
        }
    }

    /**
     * 批量删除对账记录
     */
    public function deleteMulty()
    {
        $ids = $this->request->post('ids', '');
        if (empty($ids)) {
            $this->error('请选择要删除的记录');
        }

        $ids = explode(',', $ids);
        $reconciliation = new ReconciliationModel();
        $result = $reconciliation->whereIn('id', $ids)->delete();

        if ($result !== false) {
            $this->success("批量删除成功，共删除 {$result} 条记录");
        } else {
            $this->error('批量删除失败');
        }
    }

    /**
     * 获取对账详情
     */
    public function getReconciliationDetail()
    {
        $id = $this->request->post('id');
        if (empty($id)) {
            $this->error('参数错误');
        }

        try {
            $reconciliation = ReconciliationModel::where('id', $id)->find();
            if (!$reconciliation) {
                $this->error('对账记录不存在');
            }

            // 处理发票字段，添加完整域名
            $request = \think\Request::instance();
            $domain = $request->domain();
            if (!empty($reconciliation->invoice)) {
                $invoice = json_decode($reconciliation->invoice, true);
                if (is_array($invoice)) {
                    foreach ($invoice as $key => $value) {
                        $invoice[$key] = $domain . $value;
                    }
                    $reconciliation->invoice = $invoice;
                }
            }

            $this->success('获取成功', $reconciliation);
        } catch (\Exception $e) {
            $this->error('获取失败：' . $e->getMessage());
        }
    }

    /**
     * 异步导出（提交任务后立即结束响应，后台继续处理）
     */
    public function exportAsync($params)
    {
        // 生成导出任务ID
        $taskId = uniqid('export_');

        // 读取前端参数
        $fieldsStr = (string)$this->request->post('fields', '');
        $idsStr = (string)($params['ids'] ?? $this->request->post('ids', ''));

        if ($fieldsStr === '') {
            $this->error('请选择要导出的字段');
        }
        if ($idsStr === '') {
            $this->error('请选择要导出的数据');
        }

        // 规范化
        $fieldsStr = trim($fieldsStr, ", \t\n\r");
        $idsStr = trim($idsStr, ", \t\n\r");

        // 入库
        Db::name('export_tasks')->insert([
            'task_id' => $taskId,
            'user_id' => (int)$this->auth->id,
            'fields' => $fieldsStr,
            'ids' => $idsStr,
            'status' => 'pending',
            'progress' => 0,
            'createtime' => date('Y-m-d H:i:s')
        ]);

        // 立即返回JSON响应，避免后续再发送header（Linux下更严格）
        $resp = [
            'code' => 1,
            'msg' => '导出任务已提交',
            'time' => (string)time(),
            'data' => ['task_id' => $taskId]
        ];
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($resp, JSON_UNESCAPED_UNICODE);

        if (function_exists('fastcgi_finish_request')) {
            // 结束HTTP响应，让客户端尽快拿到结果
            fastcgi_finish_request();
        } else {
            // 兼容环境：尽量把输出刷给客户端
            @ob_flush();
            @flush();
        }

        // 响应已结束：在后台继续处理任务（不要输出任何内容/不要发送header）
        ignore_user_abort(true);
        $this->processExportTaskBackground($taskId);
        exit;
    }

    /**
     * 查询导出状态
     */
    public function getExportStatus()
    {
        $taskId = $this->request->post('task_id');
        if (empty($taskId)) {
            $this->error('缺少任务ID');
        }
        
        $task = Db::name('export_tasks')->where('task_id', $taskId)->find();
        if (!$task) {
            $this->error('任务不存在');
        }
        
        $result = [
            'task_id' => $task['task_id'],
            'status' => $task['status'],
            'createtime' => $task['createtime']
        ];
        
        if ($task['status'] === 'completed') {
            // 构建完整的下载URL
            $request = \think\Request::instance();
            $domain = $request->domain();
            $fileUrl = $task['file_url'] ?? '';
            
            if ($fileUrl) {
                if (strpos($fileUrl, 'http') !== 0) {
                    $result['download_url'] = $domain . $fileUrl;
                } else {
                    $result['download_url'] = $fileUrl;
                }
            } else {
                $result['download_url'] = '';
            }
            
            $result['completetime'] = $task['completetime'];
        } elseif ($task['status'] === 'failed') {
            $result['error_msg'] = $task['error_msg'];
        } elseif ($task['status'] === 'processing') {
            $result['progress'] = $task['progress'] ?? 0;
        }
        
        $this->success('查询成功', $result);
    }

    /**
     * 后台处理导出任务（真正的异步）
     */
    private function processExportTaskBackground($taskId)
    {
        // 更新状态为处理中
        Db::name('export_tasks')->where('task_id', $taskId)->update([
            'status' => 'processing',
            'progress' => 0
        ]);
        
        try {
            $task = Db::name('export_tasks')->where('task_id', $taskId)->find();
            // fields 为逗号字符串
            $fieldsStr = (string)$task['fields'];
            $fields = array_filter(array_map('trim', explode(',', $fieldsStr)));
            if (empty($fields)) {
                $fields = ['id','productName','name','amount','reconciletime'];
            }
            // 从任务读取 ids（逗号分隔、单个ID或 JSON 兜底）
            $idsRaw = (string)($task['ids'] ?? '');
            $idsArr = [];
            if ($idsRaw !== '') {
                if (strpos($idsRaw, ',') !== false) {
                    // 多个ID，用逗号分隔
                    $idsArr = array_filter(array_map('trim', explode(',', $idsRaw)));
                } else {
                    // 单个ID或JSON格式
                    $decoded = json_decode($idsRaw, true);
                    if (is_array($decoded)) {
                        $idsArr = $decoded;
                    } else {
                        // 单个ID的情况
                        $idsArr = [$idsRaw];
                    }
                }
            }
            if (empty($idsArr)) {
                throw new \Exception('未提供导出ID列表');
            }

            // 生成CSV文件（写头后流式写入每一批）
            $filename = '对账记录_' . date('YmdHis') . '.csv';
            $savePath = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'excel';
            if (!is_dir($savePath)) {
                mkdir($savePath, 0755, true);
            }
            $filePath = $savePath . DS . $filename;
            $fp = fopen($filePath, 'w');
            fwrite($fp, "\xEF\xBB\xBF");
            $headers = $this->getExportHeaderTitles($fields);
            fputcsv($fp, $headers);

            $batchSize = 500;
            $total = count($idsArr);
            for ($i = 0; $i < $total; $i += $batchSize) {
                $batchIds = array_slice($idsArr, $i, $batchSize);
                $batchList = Db::name('reconciliation r')
                    ->join('fa_user s', 'r.staff_id = s.id', 'left')
                    ->join('fa_user u', 'r.user_id = u.id', 'left')
                    ->field('r.*, s.name as staff_name, u.name as user_name')
                    ->whereIn('r.id', $batchIds)
                    ->order('r.id', 'asc')
                    ->select();

                if ($batchList) {
                    $this->streamCsvRows($fp, $batchList, $fields);
                }
                $progress = round((($i + count($batchIds)) / $total) * 100);
                Db::name('export_tasks')->where('task_id', $taskId)->update([
                    'progress' => min(100, $progress)
                ]);
                usleep(30000);
            }

            fclose($fp);

            // 更新任务状态
            $fileUrl = '/uploads/excel/' . $filename;
            Db::name('export_tasks')->where('task_id', $taskId)->update([
                'status' => 'completed',
                'file_url' => $fileUrl,
                'completetime' => date('Y-m-d H:i:s'),
                'progress' => 100
            ]);
            
        } catch (\Exception $e) {
            Db::name('export_tasks')->where('task_id', $taskId)->update([
                'status' => 'failed',
                'error_msg' => $e->getMessage()
            ]);
        }
    }

    /**
     * 向后兼容：旧前端仍调用 exportExcelAsync，仅使用 ids 和 fields
     */
    public function exportExcelAsync()
    {
        $fields = (string)$this->request->post('fields', '');
        $ids = (string)$this->request->post('ids', '');
        $params = ['fields' => $fields, 'ids' => $ids];
        return $this->exportAsync($params);
    }

    /**
     * 下载导出文件（独立下载接口，此处才设置下载header）
     */
    public function downloadExport()
    {
        $taskId = $this->request->get('task_id', $this->request->post('task_id', ''));
        if (empty($taskId)) {
            $this->error('缺少任务ID');
        }

        $task = Db::name('export_tasks')->where('task_id', $taskId)->find();
        if (!$task || $task['status'] !== 'completed' || empty($task['file_url'])) {
            $this->error('任务未完成或文件不存在');
        }

        $filePath = ROOT_PATH . 'public' . str_replace('/', DIRECTORY_SEPARATOR, $task['file_url']);
        if (!is_file($filePath)) {
            $this->error('文件不存在');
        }

        $fileName = basename($filePath);
        // 使用框架响应下载（此请求内才发送header）
        return \think\Response::create($filePath, 'file')->download($fileName)->expire(3600);
    }

    /**
     * 处理导出功能（保留原有方法以兼容）
     */
    private function handleExport($params)
    {
        $fields = $this->request->post('fields');
        $selectedIds = $this->request->post('ids', []);

        if (empty($fields)) {
            $this->error('请选择要导出的字段');
        }

        $fields = explode(',', $fields);

        // 构建查询条件
        $where = $this->buildWhere($params);

        // 获取数据
        $list = Db::name('reconciliation r')
            ->join('fa_user s', 'r.staff_id = s.id', 'left')
            ->join('fa_user u', 'r.user_id = u.id', 'left')
            ->field('r.*, s.name as staff_name, u.name as user_name')
            ->where($where)
            ->order('r.id', 'desc')
            ->select();

        // 创建Excel文件
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 字段映射表
        $fieldMap = [
            'productName' => '产品名称',
            'name' => '对接人',
            'staff_name' => '负责人',
            'user_name' => '创建人',
            'amount' => '金额',
            'invoice' => '发票',
            'reconciletime' => '对账时间',
            'createtime' => '创建时间',
            'updatetime' => '更新时间'
        ];

        // 写入表头
        $col = 1;
        foreach ($fields as $field) {
            if (isset($fieldMap[$field])) {
                $sheet->setCellValueByColumnAndRow($col, 1, $fieldMap[$field]);
                $col++;
            }
        }

        // 写入数据
        $row = 2;
        foreach ($list as $item) {
            $col = 1;
            foreach ($fields as $field) {
                if (isset($fieldMap[$field])) {
                    $value = isset($item[$field]) ? $item[$field] : '';

                    // 处理特殊字段
                    switch ($field) {
                        case 'createtime':
                        case 'updatetime':
                        case 'reconciletime':
                            $value = $value ? date('Y-m-d H:i:s', strtotime($value)) : '';
                            break;
                        case 'invoice':
                            if (!empty($value) && is_string($value)) {
                                $invoice = json_decode($value, true);
                                if (is_array($invoice)) {
                                    $value = implode(', ', $invoice);
                                }
                            }
                            break;
                        case 'amount':
                            $value = floatval($value);
                            break;
                    }

                    $sheet->setCellValueByColumnAndRow($col, $row, $value);
                    $col++;
                }
            }
            $row++;
        }

        // 设置列宽
        for ($i = 1; $i <= count($fields); $i++) {
            $sheet->getColumnDimensionByColumn($i)->setWidth(15);
        }

        // 设置表头样式
        $headerStyle = [
            'font' => ['bold' => true],
            'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
            'borders' => [
                'allBorders' => ['borderStyle' => Border::BORDER_THIN]
            ],
            'fill' => [
                'fillType' => Fill::FILL_SOLID,
                'startColor' => ['rgb' => 'E0E0E0']
            ]
        ];
        $sheet->getStyle('A1:' . $sheet->getHighestColumn() . '1')->applyFromArray($headerStyle);

        // 设置数据区域样式
        $dataStyle = [
            'borders' => [
                'allBorders' => ['borderStyle' => Border::BORDER_THIN]
            ],
            'alignment' => ['vertical' => Alignment::VERTICAL_CENTER]
        ];
        $sheet->getStyle('A2:' . $sheet->getHighestColumn() . ($row - 1))->applyFromArray($dataStyle);

        // 生成文件名
        $filename = '对账数据_' . date('YmdHis') . '.xlsx';

        // 确保目录存在
        $savePath = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'excel';
        if (!is_dir($savePath)) {
            mkdir($savePath, 0755, true);
        }

        // 完整的文件保存路径
        $filePath = $savePath . DS . $filename;

        // 保存文件
        $writer = new Xlsx($spreadsheet);
        $writer->save($filePath);

        // 返回文件URL给前端
        $request = \think\Request::instance();
        $domain = $request->domain();
        $fileUrl = $domain . '/uploads/excel/' . $filename;
        $this->success('导出成功', ['url' => $fileUrl]);
    }

    /**
     * 处理批量删除
     */
    private function handleDelete($params)
    {
        $ids = $this->request->post('ids', '');
        if (empty($ids)) {
            $this->error('请选择要删除的记录');
        }

        $ids = explode(',', $ids);
        $reconciliation = new ReconciliationModel();
        $result = $reconciliation->whereIn('id', $ids)->delete();

        if ($result !== false) {
            $this->success("批量删除成功，共删除 {$result} 条记录");
        } else {
            $this->error('批量删除失败');
        }
    }

    /**
     * 构建查询条件
     */
    private function buildWhere($params)
    {
        $where = [];

        $searchKey = isset($params['searchKey']) ? $params['searchKey'] : '';
        if ($searchKey) {
            $where['r.productName|r.name|r.amount'] = ['like', "%{$searchKey}%"];
        }

        if (isset($params['productName']) && !empty($params['productName'])) {
            $where['r.productName'] = ['like', "%{$params['productName']}%"];
        }

        if (isset($params['name']) && !empty($params['name'])) {
            $where['r.name'] = ['like', "%{$params['name']}%"];
        }

        if (isset($params['staff_id']) && !empty($params['staff_id'])) {
            $where['r.staff_id'] = $params['staff_id'];
        }

        if (isset($params['user_id']) && !empty($params['user_id'])) {
            $where['r.user_id'] = $params['user_id'];
        }

        if (isset($params['amount']) && !empty($params['amount'])) {
            $where['r.amount'] = ['like', "%{$params['amount']}%"];
        }

        if (isset($params['reconciletimeStart']) && !empty($params['reconciletimeEnd'])) {
            $where['r.reconciletime'] = ['between', [$params['reconciletimeStart'], $params['reconciletimeEnd']]];
        }

        if (isset($params['createtimeStart']) && !empty($params['createtimeEnd'])) {
            $where['r.createtime'] = ['between', [$params['createtimeStart'], $params['createtimeEnd']]];
        }

        return $where;
    }

    // 生成表头标题
    private function getExportHeaderTitles($fields)
    {
        $fieldMap = [
            'id' => 'ID',
            'productName' => '产品名称',
            'name' => '对接人',
            'amount' => '金额',
            'invoice' => '发票',
            'reconciletime' => '对账时间',
            'staff_id' => '负责人',
            'user_id' => '创建人',
            'createtime' => '创建时间',
            'updatetime' => '更新时间'
        ];
        $headers = [];
        foreach ($fields as $f) {
            $headers[] = $fieldMap[$f] ?? $f;
        }
        return $headers;
    }

    // 将一批数据写入CSV
    private function streamCsvRows($fp, $rows, $fields)
    {
        foreach ($rows as $item) {
            $csvRow = [];
            foreach ($fields as $f) {
                $csvRow[] = $this->formatFieldValueForExport($f, $item);
            }
            fputcsv($fp, $csvRow);
        }
    }

    // 导出字段格式化：保证图片字段输出完整URL
    protected function formatFieldValueForExport($field, $item)
    {
        $value = isset($item[$field]) ? $item[$field] : '';
        switch ($field) {
            case 'reconciletime':
            case 'createtime':
            case 'updatetime':
                return $value ? date('Y-m-d H:i:s', strtotime($value)) : '';
            case 'staff_id':
                return isset($item['staff_name']) ? $item['staff_name'] : $value;
            case 'user_id':
                return isset($item['user_name']) ? $item['user_name'] : $value;
            case 'invoice':
                if (empty($value)) {
                    return '';
                }
                $domain = Request::instance()->domain();
                $arr = is_array($value) ? $value : json_decode($value, true);
                if (!is_array($arr)) {
                    return (strpos((string)$value, 'http') === 0) ? (string)$value : $domain . (string)$value;
                }
                $urls = [];
                foreach ($arr as $p) {
                    if (!is_string($p)) {
                        continue;
                    }
                    $urls[] = (strpos($p, 'http') === 0) ? $p : $domain . $p;
                }
                return implode(', ', $urls);
            default:
                return is_scalar($value) ? (string)$value : json_encode($value, JSON_UNESCAPED_UNICODE);
        }
    }
} 